import 'dart:math';

import 'package:flutter/widgets.dart';
import 'package:kq_flutter_core_widget/utils/kq_screen_util.dart';
import 'package:intl/intl.dart' as intl;

import '../../resources/kq_theme_colors.dart';

/// @author 高裕
/// 科学试模结果滑块
class SeekBarForScienceTestMoldResult extends StatefulWidget {
  const SeekBarForScienceTestMoldResult({
    super.key,
    this.value,
    required this.max,
    required this.min,
    required this.slider,
    required this.sliderWidth,
    required this.sliderHeight,
    this.bgColor = KqThemeColors.textOffline,
    this.exceedColor = KqThemeColors.textRed,
    this.progressHeight = 4,
    this.textOffSet = 4,
    this.canEdit = true,
    this.textColor = KqThemeColors.text59,
    this.height,
    this.callback,
    this.getState,
  });

  /// 值
  final double? value;

  /// 最大值(可溢出)
  final double max;

  /// 最小值(可溢出)
  final double min;

  /// 滑块
  final Widget slider;

  /// 滑块宽
  final double sliderWidth;

  /// 滑块高
  final double sliderHeight;

  /// 背景颜色
  final Color bgColor;

  /// 超出颜色
  final Color exceedColor;

  /// 进度条高度
  final double progressHeight;

  /// 高度
  final double? height;

  /// 是否可编辑
  final bool canEdit;

  /// 文本和进度条之间的间距
  final double textOffSet;

  /// 文本颜色
  final Color textColor;

  final Function(double value)? callback;

  /// 获取state用于独自刷新
  final Function(SeekBarForScienceTestMoldResultState state)? getState;

  @override
  State<SeekBarForScienceTestMoldResult> createState() =>
      SeekBarForScienceTestMoldResultState();
}

class SeekBarForScienceTestMoldResultState
    extends State<SeekBarForScienceTestMoldResult> {
  /// 进度(0~1)
  double progress = 0;

  /// 数据总长
  double interval = 0;

  /// 跟随标志
  final LayerLink layerLink = LayerLink();

  /// 是否在范围内点击
  bool touchInArea = false;

  /// 计算当前进度
  void _countProgress() {
    interval = widget.max - widget.min;
    if (widget.value != null) {
      progress = (widget.value! - widget.min) / interval;
      if (widget.value! < widget.min) {
        interval = (interval + (widget.min - widget.value!));
        progress = 0;
      } else if (widget.value! > widget.max) {
        interval = (interval + (widget.value! - widget.max));
        progress = 1;
      }
    } else {
      progress = 0;
    }
  }

  /// 主动刷新方法
  update() {
    if (mounted) {
      setState(() {});
    }
  }

  @override
  void initState() {
    super.initState();
    widget.getState?.call(this);
    _countProgress();
  }

  @override
  void didUpdateWidget(covariant SeekBarForScienceTestMoldResult oldWidget) {
    super.didUpdateWidget(oldWidget);
    widget.getState?.call(this);
    _countProgress();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: _seekBar(),
    );
  }

  /// 滑动条
  Widget _seekBar() {
    return LayoutBuilder(
      builder: (context, container) {
        double width = container.maxWidth;
        double height = widget.height ?? container.maxHeight;
        double bgWidth = width - widget.sliderWidth;
        return GestureDetector(
          onHorizontalDragStart: (e) {
            touchInArea = e.localPosition.dx <=
                    (progress * bgWidth + (widget.sliderWidth * 1.5)) &&
                e.localPosition.dx >=
                    progress * bgWidth - (widget.sliderWidth / 2);
          },
          onHorizontalDragUpdate: widget.canEdit
              ? (e) {
                  if (!touchInArea) {
                    return;
                  }
                  progress += e.delta.dx / bgWidth;
                  if (progress <= 0) {
                    progress = 0;
                  } else if (progress >= 1) {
                    progress = 1;
                  }
                  widget.callback?.call(interval * progress + widget.min);
                  setState(() {});
                }
              : null,
          child: Stack(
            children: [
              SizedBox(
                width: double.infinity,
                height: height,
                child: RepaintBoundary(
                  child: CustomPaint(
                    painter: _ProgressPainter(
                      max: widget.max,
                      min: widget.min,
                      interval: interval,
                      textOffSet: widget.textOffSet,
                      textColor: widget.textColor,
                      value: widget.canEdit
                          ? interval * progress + widget.min
                          : widget.value,
                      progressHeight: widget.progressHeight,
                      sliderWidth: widget.sliderWidth,
                      sliderHeight: widget.sliderHeight,
                      bgColor: widget.bgColor,
                      exceedColor: widget.exceedColor,
                    ),
                  ),
                ),
              ),
              if (widget.value != null)
                Positioned(
                    left: progress * bgWidth,
                    top: (height / 2) - (widget.sliderHeight / 2),
                    child: widget.slider),
            ],
          ),
        );
      },
    );
  }
}

/// 科学试模的进度条(可越界，自带)
class _ProgressPainter extends CustomPainter {
  _ProgressPainter({
    required this.max,
    required this.min,
    required this.interval,
    required this.textOffSet,
    required this.textColor,
    required this.sliderWidth,
    required this.sliderHeight,
    required this.bgColor,
    required this.exceedColor,
    this.value,
    this.progressHeight = 4,
  });

  final Paint _paint = Paint()..style = PaintingStyle.fill;

  /// 值
  final double? value;

  /// 最大值(可溢出)
  final double max;

  /// 最小值(可溢出)
  final double min;

  /// 数据总长
  final double interval;

  /// 文本和进度条之间的间距
  final double textOffSet;

  /// 文本颜色
  final Color textColor;

  /// 背景颜色
  final Color bgColor;

  /// 超出颜色
  final Color exceedColor;

  /// 进度条高度
  final double progressHeight;

  /// 滑块宽
  final double sliderWidth;

  /// 滑块高
  final double sliderHeight;

  /// 起始结束的文本位置
  double? minTextPosition;
  double? maxTextPosition;

  /// 内部进度，value换算得出，0~1
  double progress = 0;

  final numberFormat = intl.NumberFormat("#.##");

  @override
  void paint(Canvas canvas, Size size) {
    double widthLeft = sliderWidth / 2;
    double widthRight = size.width - (sliderWidth / 2);
    double totalWidth = size.width - sliderWidth;
    TextPainter minPainter =
        createTextPainter(numberFormat.format(min), textColor);
    TextPainter maxPainter =
        createTextPainter(numberFormat.format(max), textColor);
    TextPainter? valuePainter;
    if (value != null) {
      valuePainter = createTextPainter(numberFormat.format(value), textColor);
    }
    double emptyHeight = (size.height / 2) - (progressHeight / 2);
    double progressBottom = (size.height / 2) + (progressHeight / 2);

    if (value != null) {
      if (value! <= max && value! >= min) {
        // 正常
        _paint.color = bgColor;
        Offset leftTop = Offset(widthLeft, emptyHeight);
        Offset rightBottom = Offset(widthRight, progressBottom);
        minTextPosition = leftTop.dx;
        maxTextPosition = rightBottom.dx - maxPainter.width;
        canvas.drawRect(Rect.fromPoints(leftTop, rightBottom), _paint);
        progress = (value! - min) / (max - min);
        drawCaps(canvas, size, bgColor, bgColor);
      } else if (value! < min) {
        // 左侧超出
        _paint.color = exceedColor;
        Offset leftTop1 = Offset(widthLeft, emptyHeight);
        Offset rightBottom1 = Offset(
            totalWidth * ((min - value!) / interval) + (sliderWidth / 2),
            progressBottom);
        canvas.drawRect(Rect.fromPoints(leftTop1, rightBottom1), _paint);
        _paint.color = bgColor;
        Offset leftTop2 = Offset(rightBottom1.dx, emptyHeight);
        Offset rightBottom2 = Offset(widthRight, progressBottom);
        canvas.drawRect(Rect.fromPoints(leftTop2, rightBottom2), _paint);
        minTextPosition = (leftTop2.dx - widthLeft) < (minPainter.width / 2)
            ? widthLeft
            : leftTop2.dx - (minPainter.width / 2);
        maxTextPosition = rightBottom2.dx - maxPainter.width;
        progress = 0;
        drawCaps(canvas, size, exceedColor, bgColor);
      } else if (value! > max) {
        // 右侧超出
        _paint.color = bgColor;
        Offset leftTop1 = Offset(widthLeft, emptyHeight);
        Offset rightBottom1 = Offset(
            totalWidth * ((max - min) / interval) + (sliderWidth / 2),
            progressBottom);
        canvas.drawRect(Rect.fromPoints(leftTop1, rightBottom1), _paint);
        minTextPosition = leftTop1.dx;
        maxTextPosition = (widthRight - rightBottom1.dx) < maxPainter.width / 2
            ? rightBottom1.dx -
                (maxPainter.width - (widthRight - rightBottom1.dx))
            : rightBottom1.dx - (maxPainter.width / 2);
        _paint.color = exceedColor;
        Offset leftTop2 = Offset(rightBottom1.dx, emptyHeight);
        Offset rightBottom2 = Offset(widthRight, progressBottom);
        canvas.drawRect(Rect.fromPoints(leftTop2, rightBottom2), _paint);
        progress = 1;
        drawCaps(canvas, size, bgColor, exceedColor);
      }
    } else {
      // 无值
      _paint.color = bgColor;
      Offset leftTop = Offset(widthLeft, emptyHeight);
      Offset rightBottom = Offset(widthRight, progressBottom);
      minTextPosition = leftTop.dx;
      maxTextPosition = rightBottom.dx - maxPainter.width;
      canvas.drawRect(Rect.fromPoints(leftTop, rightBottom), _paint);
      progress = 0;
      drawCaps(canvas, size, bgColor, bgColor);
    }

    // 画上下限
    minPainter.paint(
        canvas, Offset(minTextPosition!, progressBottom + textOffSet));
    maxPainter.paint(
        canvas, Offset(maxTextPosition!, progressBottom + textOffSet));

    // 画值文本
    if (valuePainter != null) {
      Offset pointCenter =
          Offset(widthLeft + (totalWidth * progress), size.height / 2);
      valuePainter.paint(
          canvas,
          Offset(
              pointCenter.dx - (valuePainter.width / 2),
              pointCenter.dy -
                  (sliderHeight / 2) -
                  textOffSet -
                  valuePainter.height));
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }

  /// 绘制头尾线帽
  void drawCaps(Canvas canvas, Size size, Color startColor, Color endColor) {
    _paint.color = startColor;
    canvas.drawArc(
        Rect.fromCircle(
            center: Offset(sliderWidth / 2, size.height / 2),
            radius: progressHeight / 2),
        pi / 2,
        pi,
        true,
        _paint);
    _paint.color = endColor;
    canvas.drawArc(
        Rect.fromCircle(
            center: Offset(size.width - (sliderWidth / 2), size.height / 2),
            radius: progressHeight / 2),
        pi * 1.5,
        pi,
        true,
        _paint);
  }

  /// 生成绘制文本，但是先不绘制到画布上
  TextPainter createTextPainter(String text, Color color) {
    TextPainter textPainter = TextPainter(
      text: TextSpan(
        text: text,
        style: TextStyle(
          color: color,
          fontSize: 12.sp,
          height: 1,
        ),
      ),
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();
    return textPainter;
  }
}
